package bsts.view.util;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
/*
 * Author 		: Lee Zhong De Rollei
 * Student ID	: A0079953L
 */
public class FieldPanel extends JPanel
{
	/*Variable=======================================================================================================*/
	
	//required as it references serializable objects for binary saving
	private static final long serialVersionUID = 1L;
	//List of types the field Panel can handle
	public enum PnlType {
		Text, TextField, RadioBtns, ComboBox, TextArea;
	}	
	//FieldPanel Properties
	private PnlType type;
	private String fieldName,fieldValue;	
	private int height,fieldNameWidth,fieldValueWidth ;
	private ArrayList<String> options = new ArrayList<String>();
	//UI Controls
	private JTextField tf;
	private JTextArea ta;
	private ButtonGroup bGroup;
	private JComboBox cBox;
	private JPanel pnlFieldLbl,pnlCol,pnlFieldValue;
	//Action Listener & Command
	private ActionListener actionListener;
	private String actionCmd;
	
	
	
	/*Constructors=======================================================================================================*/
	public FieldPanel(PnlType type, String fieldName, String fieldValue, int height,int fieldNameWidth, int fieldValueWidth) {
		this.type = type;
		this.fieldName = fieldName;
		this.fieldValue = fieldValue;
		this.height = height;
		this.fieldNameWidth = fieldNameWidth;
		this.fieldValueWidth = fieldValueWidth;
		initializePanel();

	}
	
	public FieldPanel(PnlType type,String fieldName, String fieldValue, int height,int fieldNameWidth, int fieldValueWidth,Class<?> options) {
		this.type = type;
		this.fieldName = fieldName;
		this.fieldValue = fieldValue;
		this.height = height;
		this.fieldNameWidth = fieldNameWidth;
		this.fieldValueWidth = fieldValueWidth;
		this.options = getArrayList(options);
		initializePanel();
	}
				
	public FieldPanel(PnlType type,String fieldName, String fieldValue, int height,int fieldNameWidth, int fieldValueWidth,Class<?> options,ActionListener actionListener, String actionCmd) {
		this.type = type;
		this.fieldName = fieldName;
		this.fieldValue = fieldValue;
		this.height = height;
		this.fieldNameWidth = fieldNameWidth;
		this.fieldValueWidth = fieldValueWidth;
		this.options = getArrayList(options);
		this.actionListener = actionListener;
		this.actionCmd = actionCmd;		
		initializePanel();
	}
	
	/*Initiealize Field Panel based on Pnl Type==========================================================================*/
	private void initializePanel(){
		pnlFieldLbl = new JPanel();
		pnlCol = new JPanel();
		pnlFieldValue = new JPanel();
		
		switch (this.type){
		case Text: initializeText(); break;
		case TextField: initializeTextField(); break;
		case TextArea: initializeTextArea(); break;
		case RadioBtns: initializeRadioBtns(); break;
		case ComboBox: initializeComboBox(); break;
	}

	


}
	
	private void initializeText(){
		
		//Display Label
		pnlFieldLbl.setLayout(new FlowLayout(FlowLayout.LEFT));
		pnlFieldLbl.setPreferredSize(new Dimension(this.fieldNameWidth,this.height));
		pnlFieldLbl.add(new JLabel(this.fieldName));
		//Display ":"
		pnlCol.setLayout(new FlowLayout(FlowLayout.LEFT));
		pnlCol.setPreferredSize(new Dimension(10,this.height));
		pnlCol.add(new JLabel(":"));
		//Display Text		
		pnlFieldValue.setLayout(new FlowLayout(FlowLayout.LEFT));		
		pnlFieldValue.setPreferredSize(new Dimension(this.fieldValueWidth,this.height));
		pnlFieldValue.add(new JLabel(" "  + this.fieldValue));
		//Pack components
		packComponents();
		
	}
	
	private void initializeTextField(){
		
		//Display Label
		pnlFieldLbl.setLayout(new FlowLayout(FlowLayout.LEFT));
		pnlFieldLbl.setPreferredSize(new Dimension(this.fieldNameWidth,this.height));
		pnlFieldLbl.add(new JLabel(this.fieldName));
		//Display ":"
		pnlCol.setLayout(new FlowLayout(FlowLayout.LEFT));
		pnlCol.setPreferredSize(new Dimension(20,this.height));
		pnlCol.add(new JLabel(":"));
		//Display Text
		tf = new JTextField(" "  + this.fieldValue);
		pnlFieldValue.setLayout(new GridLayout(1,1));
		pnlFieldValue.setPreferredSize(new Dimension(this.fieldValueWidth,this.height));
		pnlFieldValue.add(tf);				
		//Pack components
		packComponents();
		
	}
	
	private void initializeTextArea(){
		
		//Instantiate Text Area & it properties
		ta = new JTextArea(this.fieldValue);
		ta.setBorder(BorderFactory.createLineBorder(Color.black, 1));
		ta.setPreferredSize(new Dimension(this.fieldValueWidth,this.height-10));
		ta.setLineWrap(true);

		//Display Label
		pnlFieldLbl.setLayout(new FlowLayout(FlowLayout.LEFT));
		pnlFieldLbl.setPreferredSize(new Dimension(this.fieldNameWidth,this.height));
		pnlFieldLbl.add(new JLabel(this.fieldName));
		//Display ":"
		pnlCol.setLayout(new FlowLayout(FlowLayout.LEFT));
		pnlCol.setPreferredSize(new Dimension(20,this.height));
		pnlCol.add(new JLabel(":"));
		//Display Text
		pnlFieldValue.setLayout(new FlowLayout(FlowLayout.CENTER));
		pnlFieldValue.setPreferredSize(new Dimension(this.fieldValueWidth,this.height));
		pnlFieldValue.add(ta);
		
		
		packComponents();
		
	}
	
	private void initializeRadioBtns(){
		//Declare local variables
		JRadioButton jRadioButton = null;
		bGroup = new ButtonGroup();
		String option;
		
		//Display Label
		pnlFieldLbl.setLayout(new FlowLayout(FlowLayout.LEFT));
		pnlFieldLbl.setPreferredSize(new Dimension(this.fieldNameWidth,this.height));
		pnlFieldLbl.add(new JLabel(this.fieldName));
		//Display ":"
		pnlCol.setLayout(new FlowLayout(FlowLayout.LEFT));
		pnlCol.setPreferredSize(new Dimension(10,this.height));
		pnlCol.add(new JLabel(":"));			
		//Radio button list
		pnlFieldValue.setLayout(new FlowLayout(FlowLayout.LEFT));
		pnlFieldValue.setPreferredSize(new Dimension(this.fieldValueWidth,this.height+10));
		for(int i=0;i<this.options.size();i++)
		{
			option = this.options.get(i).toString();
			jRadioButton = new JRadioButton(option);
			if(option.toUpperCase().equals(this.fieldValue.toUpperCase())){
				jRadioButton.setSelected(true);
			}
			jRadioButton.addActionListener(this.actionListener);
			jRadioButton.setActionCommand(this.actionCmd);
			bGroup.add(jRadioButton);
			pnlFieldValue.add(jRadioButton);
		}
	
		packComponents();


		
	}

	private void initializeComboBox(){
		
		//Display Label
		pnlFieldLbl.setLayout(new FlowLayout(FlowLayout.LEFT));
		pnlFieldLbl.setPreferredSize(new Dimension(this.fieldNameWidth,this.height));
		pnlFieldLbl.add(new JLabel(this.fieldName));
		//Display ":"
		pnlCol.setLayout(new FlowLayout(FlowLayout.LEFT));
		pnlCol.setPreferredSize(new Dimension(10,this.height));
		pnlCol.add(new JLabel(":"));
		
		cBox = new JComboBox();
		cBox.setPreferredSize(new Dimension(this.fieldValueWidth,this.height));
		String option;
		for(int i=0;i<this.options.size();i++)
		{
			option = this.options.get(i).toString();
			cBox.addItem(option);
			if(option.toUpperCase().equals(this.fieldValue.toUpperCase())){
				cBox.setSelectedIndex(i);
			}
			
			pnlFieldValue.add(cBox);
		}
	
		packComponents();


		
	}
	
	private void packComponents(){
		add(this.pnlFieldLbl,new GridBagConstraints());
		add(this.pnlCol,new GridBagConstraints());
		add(this.pnlFieldValue,new GridBagConstraints());
		
	}

	/*This function helps to convert enum variable into arraylist*/
	private static ArrayList<String> getArrayList(Class<?> options){
		
		ArrayList<String> aList = new ArrayList<String>();
		
	    for (Object obj : options.getEnumConstants()) {             
	    	aList.add(obj.toString()) ; 
	    	} 
	
		return aList;
	}

	/*Other public function===========================================================================================*/
	
	/*Get the value that is in this field control, currently the field control can only capture single value hence it can
	  only return 1 single value. */
	public String getValue()
	{
		switch (this.type){
		case TextField:
			if(this.tf !=null){				
				return tf.getText();
			}
		break;
		case TextArea:
			if(this.ta !=null){				
				return ta.getText();
			}
		break;
		case RadioBtns:
			if(this.bGroup !=null){
				for (Enumeration<AbstractButton> e=this.bGroup.getElements(); e.hasMoreElements(); ) {
					JRadioButton b = (JRadioButton)e.nextElement();
		            if (b.getModel() == this.bGroup.getSelection()) {
		                return b.getText();
		            }
				}
			}
		break;
		case ComboBox: 
			if(this.cBox!=null){
				return this.cBox.getSelectedItem().toString();
				}
			break;
		}
		return "";
	}

	/*Set the value that is in this field control, for example default combox selected item can be done outside this(fieldcontrol)
	 to provide flexibility
	*/
	public boolean setValue(String val){
		switch (this.type){
		case TextField:
			if(this.tf !=null){				
				 tf.setText(val);
			}
		break;
		case TextArea:
			if(this.ta !=null){				
				 ta.setText(val);
				 return true;
			}
		break;
		case RadioBtns:
			if(this.bGroup !=null){
				for (Enumeration<AbstractButton> e=this.bGroup.getElements(); e.hasMoreElements(); ) {
					JRadioButton b = (JRadioButton)e.nextElement();
		            if (b.getText().toUpperCase().equals(val.toUpperCase())) {
		                b.setSelected(true);
		            }else{		                	
		                b.setSelected(false); 
		            }
				}
				return true;
			}
		break;
		case ComboBox: 
			if(this.cBox !=null){
				for (int i=0; i<cBox.getItemCount();i++ ) {
		            if (cBox.getItemAt(i).toString().toUpperCase().equals(val.toUpperCase())) {
		               cBox.setSelectedIndex(i);
		           		return true;
		            }
				}
			}		
			break;
		}
		
		return false;
	}

	
	/*allow caller to further set the properties of the control*/
	public Object getControl(){
		switch (this.type){
		case TextField:
			if(this.tf !=null){				
				return this.tf;
			}
		break;
		case TextArea:
			if(this.ta !=null){				
				return this.ta;
			}
		break;
		case RadioBtns:
			if(this.bGroup !=null){				
				return this.bGroup;
			}
		break;
		case ComboBox: 
			if(this.cBox !=null){				
				return this.cBox;
			}
		}
		return null;
	}
}

